/*
 * Team Name: Team Sasquatch
 * Cody Sharff
 * Anthony Rios
 * Prince Kishore
 * Travis Drake
 */

package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Observable;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import model.Auction;
import model.MasterCollection;
import model.SortType;
import model.User;
import model.UserType;


/**
 * The Calendar GUI.
 * 
 * 
 * Loosely based on this tutorial.
 * http://www.dreamincode.net/forums/topic/25042-creating-a-calendar-viewer-application/page__st__15
 * 
 * Navigation buttons aside, actual calendar panel was
 * written from scratch by Travis :D as well as all math involving dates...
 * Serious pain, I'm telling you.
 * 
 * 
 * @author Prince Kishore
 * @author Travis Drake
 *         Heavy heavy revisions, complete rewrite of calendar panel to provide
 *         more functionality.
 *
 */
public class CalendarGUI extends Observable
{
    public static final String[] MONTHS = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
    public static final String[] DAYS_OF_WEEK = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    public static final String CALENDAR_TEXT = "Calendar";
    public static final String VIEW_BUTTON = "View";
    public static final String VIEW_BIDS_BUTTON = "View bids";
	private final int WIDTH = 700;
	private final int HEIGHT = 462;
	private JLabel my_month_label;
	private JLabel my_year_label;
	private JButton my_prev_button;
	private JButton my_next_button;
	private JButton my_auction_list_button;
	private JButton my_bids_button;
	private JComboBox my_year_drop_down;
	private JFrame my_main_frame;
	private Container my_pane;
	private JPanel my_calendar_panel;
	private int my_actual_month, 
				my_actual_year, my_current_month, 
				my_current_year, my_actual_day;
	private User my_cur_user;
	private MasterCollection  my_master_collection;
    private JPanel my_test_panel;
    
    /**
	 * Constructs a CalendarGUI object.
	 * 
	 * @param the_cur_user Current user.
	 * 
	 * @requires the_cur_user != null
	 * @requires the_master_collection != null
	 * @ensures CalendarGUI
	 */
	public CalendarGUI (User the_cur_user, MasterCollection the_master_collection)
	{
		my_cur_user = the_cur_user;
		my_master_collection = the_master_collection;
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (ClassNotFoundException e) {}
        catch (InstantiationException e) {}
        catch (IllegalAccessException e) {}
        catch (UnsupportedLookAndFeelException e) {}
        
        prepareFrame();
        createControllers();
        addControls();
        setBounds();
        
        
        obtainDate();
        formatCalendar();   
        refreshCalendar(my_actual_month, my_actual_year);
        addActions();
        my_calendar_panel.setName("Calendar");
        my_auction_list_button.setBackground(null);
        my_bids_button.setBackground(null);
	}
	
	public int getActualYear() {
		return my_actual_year;
	}
	
	public int getActualMonth() {
		return my_actual_month;
	}
	
	public int getActualDay() {
		return my_actual_day;
	}
	
	/**
	 * Formats the calendar and sets headers for the days.
	 */
	private void formatCalendar()
	{
		//Prepare Calendar
		for (int i = my_actual_year - 10; i <= my_actual_year + 10; i++)
		{
			my_year_drop_down.addItem(String.valueOf(i));
		}

		//Setting the border
		my_calendar_panel.setBorder(BorderFactory.createTitledBorder(CALENDAR_TEXT));
		my_calendar_panel.setBackground(new Color(150, 248, 255));

		//Font of month label
		my_month_label.setFont(new Font("Arial", Font.BOLD, 16));

	}
	
	
	
	/**
	 * Adds the action listeners to the buttons.
	 */
	private void addActions()
	{
		my_prev_button.addActionListener(new previousButtonAction());
		my_next_button.addActionListener(new nextButtonAction());
		my_year_drop_down.addActionListener(new yearDropDownAction());
		my_auction_list_button.addActionListener(new viewAuctionAction());
	}
	
	
	
	/**
	 * Gets the actual date of today.
	 */
	private void obtainDate()
	{
		GregorianCalendar calendar = new GregorianCalendar();
		my_actual_day = calendar.get(GregorianCalendar.DAY_OF_MONTH);
		my_actual_month = calendar.get(GregorianCalendar.MONTH);
		my_actual_year = calendar.get(GregorianCalendar.YEAR);
		my_current_month = my_actual_month;
		my_current_year = my_actual_year;		
	}
	
	
	/**
	 * Creates the labels, buttons, and JTable for the calendar.
	 */
	private void createControllers()
	{
		my_month_label = new JLabel ("January");
		my_year_label = new JLabel ("Change Year:");
		my_year_drop_down = new JComboBox();
		my_prev_button = new JButton("<<");
		my_next_button = new JButton(">>");
		my_auction_list_button = new JButton("Auction List");
		my_bids_button = new JButton("View Bids");

		my_calendar_panel = new JPanel(null); //creates panel to place components
	}
	
	
	
	/**
	 * Creates the frame and adds the calendar panel
	 * to the frame.
	 */
	private void prepareFrame()
	{
		my_main_frame = new JFrame("AuctionCentral Calendar");
		my_main_frame.setSize(new Dimension(WIDTH, HEIGHT));
		my_pane = my_main_frame.getContentPane();
		my_pane.setLayout(null);
		my_main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	
	
	/**
	 * Adds buttons and other controls to the calendar.
	 */
	private void addControls()
	{
		my_pane.add(my_calendar_panel);
		my_calendar_panel.add(my_month_label);
		my_calendar_panel.add(my_year_label);
		my_calendar_panel.add(my_year_drop_down);
		my_calendar_panel.add(my_prev_button);
		my_calendar_panel.add(my_next_button);
		my_calendar_panel.add(my_auction_list_button);

        if (my_cur_user.my_user_type == UserType.BIDDER)
        {
        	my_bids_button.addActionListener(new viewBidsAction());
            my_calendar_panel.add(my_bids_button);
        }
	}
	
	
	
	/**
	 * Sets the location of each item on the calendar.
	 */
	private void setBounds()
	{
		my_calendar_panel.setBounds(5, 10, 475, 560);
		my_month_label.setBounds(360 - my_month_label.getPreferredSize().width/2, 25, my_month_label.getPreferredSize().width, 25);
		my_year_label.setBounds(310, 525, 80, 20);
		my_year_drop_down.setBounds(385, 525, 80, 20);
		my_prev_button.setBounds(10, 20, 50, 25);
		my_next_button.setBounds(65, 20, 50, 25);
		my_auction_list_button.setBounds(710 - my_auction_list_button.getPreferredSize().width, 20, my_auction_list_button.getPreferredSize().width,
		            my_auction_list_button.getPreferredSize().height);
		my_bids_button.setBounds(710 - my_auction_list_button.getPreferredSize().width - my_bids_button.getPreferredSize().width, 20, 
		            my_bids_button.getPreferredSize().width, my_bids_button.getPreferredSize().height);
	}
	
	
	
	/**
	 * Refreshes the calendar for any changes to the month or year and 
	 * redisplays it. Does massive calculations on each day box.
	 * @author Travis Drake
	 * @version May 27 2012
	 * 
	 * @param the_month The month the calendar is set to.
	 * @param the_year The year in which above month exists.
	 * 
	 * @requires the_month >= 0 && the_month <= 11
	 * @requires the_year > 1000
	 * @ensures CalendarGUI //refreshed
	 */
	private void refreshCalendar(int the_month, int the_year)
	{
		
		int start_of_month;
		my_prev_button.setEnabled(true);
		my_next_button.setEnabled(true);
		my_next_button.setBackground(null);
		my_prev_button.setBackground(null);
		
		//Limits the years so that you cannot access a date too early or too late
		if (the_month == 0 && the_year <= 2012) //removed - 10, no reason to go 10 years back 
		                                                  //from whenever they'd start computerized auctions.
		{
			my_prev_button.setEnabled(false);
		}
		
		if (the_month == 11 && the_year >= my_actual_year + 1)
		{
			my_next_button.setEnabled(false);
		}
		
		my_month_label.setText(MONTHS[the_month]); //updates the month label
		my_month_label.setBackground(null);
		
		my_month_label.setBounds(360 - my_month_label.getPreferredSize().width/2, 25, my_month_label.getPreferredSize().width, 25); // Re-aligns the label
		
		my_year_drop_down.setSelectedItem(String.valueOf(the_year));
		my_year_drop_down.setBackground(null);
		final Calendar cur_day = Calendar.getInstance();
		//Get 1st day of the month and the number of days in that month
		final GregorianCalendar calendar = new GregorianCalendar(the_year, the_month, 1);
		start_of_month = calendar.get(GregorianCalendar.DAY_OF_WEEK);
		int end_of_month = calendar.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
        
		if (my_test_panel != null)
		{
	        my_calendar_panel.remove(my_test_panel);
		}
		GridLayout test_layout = new GridLayout(6, 7);
        my_test_panel = new JPanel(test_layout);
        my_test_panel.setBounds(10, 50, 700, 462);
        my_calendar_panel.add(my_test_panel);
        int temp_day_counter = 1;
        my_test_panel.setVisible(true);
        
        for (int i = 0; i < 6 * 7; i++)
        {
            JPanel loop_panel = new JPanel();

            loop_panel.setBackground(Color.GRAY);
            loop_panel.setBorder(BorderFactory.createLineBorder(new Color(0, 50, 120)));
            my_test_panel.add(loop_panel);
            BorderLayout temp_border_layout = new BorderLayout();
            loop_panel.setLayout(temp_border_layout);
            final List<Auction> temp_auct_list = my_master_collection.getAuctions(SortType.DATE);
            int temp_auct_counter = 0;
            Calendar temp_cal = temp_auct_list.get(temp_auct_counter).getDate();
            while (temp_auct_list.size() > temp_auct_counter)
            {
                temp_cal = temp_auct_list.get(temp_auct_counter).getDate();
                if (calendar.get(GregorianCalendar.YEAR) > temp_cal.get(Calendar.YEAR) ||
                            calendar.get(GregorianCalendar.MONTH) > temp_cal.get(Calendar.MONTH) ||
                            calendar.get(GregorianCalendar.DAY_OF_MONTH) + temp_day_counter - 1 > temp_cal.get(Calendar.DAY_OF_MONTH))
                {
                    temp_auct_counter++;
                } else {
                    break;
                }
            }
            if (i + 1 >= start_of_month && i + 1 < end_of_month + start_of_month) 
            {

                
                JLabel corner_date_label = new JLabel("  " + temp_day_counter + "  ");
                corner_date_label.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
                corner_date_label.setBackground(Color.WHITE);
                temp_day_counter++;
                GridBagLayout temp_grid_bag = new GridBagLayout();
                
                GridBagConstraints c = new GridBagConstraints();    
                c.fill = GridBagConstraints.HORIZONTAL;

                c.gridx = 0;
                c.gridy = 0;
                c.gridwidth = 1;
                c.insets = new Insets(0, 3, 0, 0);
                if (my_cur_user.getType() == UserType.BIDDER)
                {
                    c.insets = new Insets(5, 5, 0, 0);
                }
                
                
                
                loop_panel.setLayout(temp_grid_bag);
                loop_panel.add(corner_date_label, c);
                
                c.insets = new Insets(0,0,0,0);
                c.gridx  = 1;
                c.gridy = 0;
                c.gridwidth = 1;
                c.weightx = 0.5;
                JPanel temp_panel = new JPanel();
                temp_panel.setBackground(null);
                loop_panel.add(temp_panel, c);
                loop_panel.setBackground(new Color(245, 248, 252));
                           
                


                c.gridx = 2;
                c.gridy = 0;
                c.gridwidth = 1;
                c.weightx = 0.0;
                JButton add_button = new JButton("+");
                add_button.setBackground(null);
                
//Adds add to day buttons
                final GregorianCalendar temp_cal_2 = new GregorianCalendar(the_year, the_month, temp_day_counter - 1);
                if (my_cur_user.getType() != UserType.BIDDER)
                {
                    if (my_master_collection.checkDateValid(temp_cal_2).size() > 0)
                    {
                        add_button.setEnabled(false);
                        loop_panel.setBackground(new Color(255, 250, 230));
                    } 
                } else {
                    
                    add_button.setEnabled(false);
                    add_button.setVisible(false);
                }


                if (temp_cal_2.get(GregorianCalendar.YEAR) == cur_day.get(Calendar.YEAR) &&
                            temp_cal_2.get(GregorianCalendar.MONTH) == cur_day.get(Calendar.MONTH) &&
                            temp_cal_2.get(GregorianCalendar.DAY_OF_MONTH) == cur_day.get(Calendar.DAY_OF_MONTH))
                {
                    loop_panel.setBackground(new Color(200, 255, 250));
                }
                add_button.addActionListener(new ActionListener()
                {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        setChanged();
                        notifyObservers(temp_cal_2);
                    }
                });
                loop_panel.add(add_button, c);
               

                c.gridx  = 0;
                c.gridy = 1;
                c.gridwidth = 3;
                c.weightx = 0.5;
                c.weighty = 0.5;
                JPanel temp_panel2 = new JPanel();
                temp_panel2.setBackground(null);
                loop_panel.add(temp_panel2, c);
                //Empty panel to fill space in the gridbaglayout.
                c.gridy = 2;
                c.gridx = 0;
                c.gridwidth = 3;
                
                if (calendar.get(GregorianCalendar.YEAR) == temp_cal.get(Calendar.YEAR) &&
                            calendar.get(GregorianCalendar.MONTH) == temp_cal.get(Calendar.MONTH) &&
                            calendar.get(GregorianCalendar.DAY_OF_MONTH) + temp_day_counter - 2 == temp_cal.get(Calendar.DAY_OF_MONTH))
                {
                    JButton auct_button = new JButton(temp_auct_list.get(temp_auct_counter).getNPO());
                    final int auct_counter_final = temp_auct_counter;
                    loop_panel.add(auct_button, c);                    auct_button.addActionListener(new ActionListener()
                    {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            setChanged();
                            notifyObservers(temp_auct_list.get(auct_counter_final));
                        }
                    });
                    temp_auct_counter++;
                    if (temp_auct_list.size() > temp_auct_counter)
                    {
                        temp_cal = temp_auct_list.get(temp_auct_counter).getDate();
                        
                    } else {
                    }
                }                
                if ((calendar.get(GregorianCalendar.YEAR) == temp_cal.get(Calendar.YEAR) &&
                            calendar.get(GregorianCalendar.MONTH) == temp_cal.get(Calendar.MONTH) &&
                            calendar.get(GregorianCalendar.DAY_OF_MONTH) + temp_day_counter - 2 == temp_cal.get(Calendar.DAY_OF_MONTH)) &&
                            temp_auct_list.size() > temp_auct_counter)
                {

                    c.gridy = 3;
                    c.gridx = 0;
                    c.gridwidth = 3;
                    c.insets = new Insets(0, 0, 5, 0);
                   JButton auct_button = new JButton(temp_auct_list.get(temp_auct_counter).getNPO());
                    final int auct_counter_final = temp_auct_counter;
                    loop_panel.add(auct_button, c);
                    auct_button.addActionListener(new ActionListener()
                    {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            System.out.println("sending auction to view back to masterGUI");
                            setChanged();
                            notifyObservers(temp_auct_list.get(auct_counter_final));
                        }
                    });
                }
                
            }
            
            
        }
	}
	
	
	
	/**
	 * The previous button action. Moves calendar back one month.
	 * @author Prince Kishore
	 * @version 5/4/12
	 *
	 */
	private class previousButtonAction implements ActionListener
	{
		public void actionPerformed(ActionEvent the_event)
		{
			if (my_current_month == 0)
			{
				my_current_month = 11;
				my_current_year -= 1;
			}
			else
			{
				my_current_month -= 1;
			}
			refreshCalendar(my_current_month, my_current_year);
		}
	}
	
	
	
	/**
	 * The next button action. Forwards the calendar by one month.
	 * @author Prince Kishore
	 * @version 5/4/12
	 *
	 */
	private class nextButtonAction implements ActionListener
	{
		public void actionPerformed(ActionEvent the_event)
		{
			//If December, add a year too else, only add a month.
			if (my_current_month == 11)
			{
				my_current_month = 0;
				my_current_year += 1;
			}
			else
			{
				my_current_month += 1;
			}
			refreshCalendar(my_current_month, my_current_year);
		}
	}
	
	
	
	/**
	 * The year drop down menu action. Changes the year.
	 * @author Prince Kishore
	 * @version 5/4/12
	 *
	 */
	private class yearDropDownAction implements ActionListener
	{
		public void actionPerformed (ActionEvent the_event)
		{
			if (my_year_drop_down.getSelectedItem() != null)
			{
				String temp = my_year_drop_down.getSelectedItem().toString();
				my_current_year = Integer.parseInt(temp);
			}
			setChanged();
			notifyObservers(null);
		}
	}
	
	
	/**
	 * the getPanel method to return the calendarPanel to display.
	 * 
	 * @author Travis Drake
	 * @return my_calendar_panel.
	 */
	public JPanel getPanel()
	{
	    return my_calendar_panel;
	}
	
	
	/**
	 * The add auction action.
	 * @author Prince Kishore
	 * @version 5/14/12
	 *
	 */
	private class viewAuctionAction implements ActionListener
	{
		public void actionPerformed (ActionEvent the_event)
		{
		    setChanged();
		    notifyObservers(VIEW_BUTTON);
		}
	}
	
	/**
	 * The add auction action.
	 * @author Prince Kishore
	 * @version 5/14/12
	 *
	 */
	private class viewBidsAction implements ActionListener
	{
		public void actionPerformed (ActionEvent the_event)
		{
		    setChanged();
		    notifyObservers(VIEW_BIDS_BUTTON);
		}
	}


    /**
     * Supposed to refresh / force repaint the calendar. 
     * Works for most purposes.
     * @author Travis Drake
     */
    public void refresh()
    {
        refreshCalendar(my_current_month, my_current_year);
        
    }
}
